﻿using AutoMapper;
using IOA.MES.Common;
using IOA.MES.DataAccess.Entity;
using IOA.MES.DataAccess.Enum;
using IOA.MES.DataAccess.VModel;
using IOA.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IOA.MES.Business
{
    public class CarryOverOderMgr
    {
        private MESContext mesDb = new MESContext("MES");

        /// <summary>
        /// 查询结转工单
        /// </summary>
        public Tuple<List<VCarryOverOrder>, int> QueryCarryOverOrders(int userId, int pageIndex, int pageSize, string workshopCode, string fromWorkOrderNo, string toToWorkOrderNo, string createdTimeRange, CarryOverOrderStatus? status)
        {
            var workShopCodes = new WorkshopMgr().QueryUserWorkshops(userId).Select(_ => _.WorkshopCode).ToList();
            var queryStr = mesDb.CarryOverOrders.AsNoTracking().Where(_ => _.Valid && workShopCodes.Contains(_.WorkshopCode));
            if (!string.IsNullOrWhiteSpace(workshopCode))
            {
                queryStr = queryStr.Where(_ => _.WorkshopCode == workshopCode);
            }
            if (!string.IsNullOrWhiteSpace(fromWorkOrderNo))
            {
                queryStr = queryStr.Where(_ => _.FromWorkOrderNo == fromWorkOrderNo);
            }
            if (!string.IsNullOrWhiteSpace(toToWorkOrderNo))
            {
                queryStr = queryStr.Where(_ => _.ToWorkOrderNo == toToWorkOrderNo);
            }
            if (!string.IsNullOrWhiteSpace(createdTimeRange))
            {
                var dates = createdTimeRange.Split(new string[] { "至" }, StringSplitOptions.RemoveEmptyEntries).ToList();
                DateTime startDate = Convert.ToDateTime(dates[0]).Date,
                         endDate = Convert.ToDateTime(dates[1]).Date.AddDays(1);

                queryStr = queryStr.Where(_ => startDate <= _.CreateTime && _.CreateTime < endDate);
            }
            if (status.HasValue)
            {
                queryStr = queryStr.Where(_ => _.Status == status.Value);
            }

            var total = queryStr.Count();
            var data = queryStr.OrderByDescending(_ => _.PkId).Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToList();
            var vList = Mapper.Map<List<VCarryOverOrder>>(data);
            var userIds = vList.Select(_ => _.CreateBy).ToList();
            var users = mesDb.Users.AsNoTracking().Where(_ => userIds.Contains(_.PkId) && _.Valid).ToList();
            vList.ForEach(_ =>
            {
                var user = users.FirstOrDefault(d => d.PkId == _.CreateBy);
                if (user != null)
                {
                    _.CNCreatedBy = user.TrueName;
                }
            });


            return new Tuple<List<VCarryOverOrder>, int>(vList, total);
        }

        /// <summary>
        /// 创建结转工单
        /// </summary>
        /// <param name="vModel"></param>
        /// <returns></returns>
        public VCarryOverOrder CreateCarryOverOrder(VCarryOverOrder vModel)
        {
            var fromWorkOrder = mesDb.WorkOrders.AsNoTracking().FirstOrDefault(_ => _.Valid && _.WorkOrderNo == vModel.FromWorkOrderNo);
            if (fromWorkOrder == null)
            {
                throw new MultiLanBizException(134008);  // 转出工单不存在
            }
            var toWorkOrder = mesDb.WorkOrders.AsNoTracking().FirstOrDefault(_ => _.Valid && _.WorkOrderNo == vModel.ToWorkOrderNo);
            if (toWorkOrder == null)
            {
                throw new MultiLanBizException(134009);  // 转入工单不存在
            }

            vModel.OrderNo = fromWorkOrder.OrderNo;
            vModel.WorkshopCode = fromWorkOrder.WorkshopCode;
            vModel.WorkshopName = fromWorkOrder.WorkshopName;

            var model = Mapper.Map<CarryOverOrder>(vModel);
            mesDb.CarryOverOrders.Add(model);
            mesDb.SaveChanges();

            model.CarryOverNo = $"{DateTime.Today.ToString("yyMMdd")}{(model.PkId % 10000):0000}";
            mesDb.SaveChanges();

            vModel = Mapper.Map<VCarryOverOrder>(model);
            return vModel;
        }

        /// <summary>
        /// 确认结转
        /// </summary>
        public void CompleteCarryOver(VCarryOverOrder model)
        {
            var entity = mesDb.CarryOverOrders.AsNoTracking().FirstOrDefault(_ => _.Valid && _.CarryOverNo == model.CarryOverNo);
            if (entity == null)
            {
                throw new MultiLanBizException(134010);  // 该结转工单不存在
            }

            mesDb.CarryOverOrders.Attach(entity);
            entity.Status = CarryOverOrderStatus.Confirmed;
            entity.ModifyBy = model.ModifyBy;
            entity.ModifyTime = DateTime.Now;

            mesDb.SaveChanges();
        }

        /// <summary>
        /// 作废结转工单
        /// </summary>
        public void DeleteCarryOverOrder(VCarryOverOrder model)
        {
            var entity = mesDb.CarryOverOrders.AsNoTracking().FirstOrDefault(_ => _.Valid && _.CarryOverNo == model.CarryOverNo);
            if (entity == null)
            {
                throw new MultiLanBizException(134010);  // 该结转工单不存在
            }
            mesDb.CarryOverOrders.Attach(entity);
            entity.Valid = false;
            entity.ModifyBy = model.ModifyBy;
            entity.ModifyTime = DateTime.Now;

            mesDb.SaveChanges();
        }

        /// <summary>
        /// 查询结转工单
        /// </summary>
        public VCarryOverOrder GetCarryOverOrder(int pkId)
        {
            VCarryOverOrder vModel = null;
            var entity = mesDb.CarryOverOrders.AsNoTracking().FirstOrDefault(_ => _.Valid && _.PkId == pkId);
            if (entity != null)
            {
                vModel = Mapper.Map<VCarryOverOrder>(entity);

                var user = new UserMgr().QueryUsers(new List<int> { vModel.CreateBy }).FirstOrDefault();
                vModel.CNCreatedBy = user?.TrueName;
            }

            return vModel;
        }

        /// <summary>
        /// 查询结转工单物料
        /// </summary>
        public List<VCarryOverProduct> QueryCarryOverProducts(string carryOverNo)
        {
            var carryOverEntity = mesDb.CarryOverOrders.AsNoTracking().FirstOrDefault(_ => _.CarryOverNo == carryOverNo && _.Valid);
            if (carryOverEntity == null)
            {
                throw new MultiLanBizException(134010);  // 该结转工单不存在
            }
            var vList = new List<VCarryOverProduct>();
            var carryOverOrder = mesDb.CarryOverOrders.AsNoTracking().FirstOrDefault(_ => _.Valid && _.CarryOverNo == carryOverNo);
            if (carryOverOrder != null)
            {
                var carryOrderProducts = mesDb.CarryOverProducts.AsNoTracking().Where(_ => _.Valid && _.CarryOverNo == carryOverOrder.CarryOverNo).ToList();
                vList.AddRange(carryOrderProducts.Select(_ => new VCarryOverProduct
                {
                    PkId = _.PkId,
                    ProductCode = _.ProductCode,
                    ProductName = _.ProductName,
                    BatchNo = _.BatchNo,
                    Quantity = _.Quantity
                }));
                if (carryOverEntity.Status == CarryOverOrderStatus.UnConfirmed)
                {
                    var allocateProducts = (from a in mesDb.AllocateOrders.AsNoTracking()
                                            join b in mesDb.AllocateProducts.AsNoTracking() on a.AllocateNo equals b.AllocateNo
                                            where a.WorkOrderNo == carryOverOrder.FromWorkOrderNo && a.Valid && b.Valid
                                            select b).ToList();
                    allocateProducts.ForEach(product =>
                    {
                        if (!vList.Any(_ => StringUtils.Equals(_.ProductCode, product.ProductCode) && StringUtils.Equals(_.BatchNo, product.BatchNo)))
                        {
                            vList.Add(new VCarryOverProduct
                            {
                                ProductCode = product.ProductCode,
                                ProductName = product.ProductName,
                                BatchNo = product.BatchNo,
                                CarryOverNo = carryOverNo
                            });
                        }
                    });

                    var comeCarryProducts = (from a in mesDb.CarryOverOrders.AsNoTracking()
                                             join b in mesDb.CarryOverProducts.AsNoTracking() on a.CarryOverNo equals b.CarryOverNo
                                             where a.ToWorkOrderNo == carryOverOrder.FromWorkOrderNo && a.Valid && b.Valid
                                             select b).ToList();
                    comeCarryProducts.ForEach(product =>
                    {
                        if (!vList.Any(_ => StringUtils.Equals(_.ProductCode, product.ProductCode) && StringUtils.Equals(_.BatchNo, product.BatchNo)))
                        {
                            vList.Add(new VCarryOverProduct
                            {
                                ProductCode = product.ProductCode,
                                ProductName = product.ProductName,
                                BatchNo = product.BatchNo,
                                CarryOverNo = carryOverNo
                            });
                        }
                    });
                }
            }

            return vList;
        }

        /// <summary>
        /// 保存结转工单物料
        /// </summary>
        public void SaveCarryOverProducts(VCarryOverOrder model, List<VCarryOverProduct> products)
        {
            var existProducts = mesDb.CarryOverProducts.AsNoTracking().Where(_ => _.CarryOverNo == model.CarryOverNo && _.Valid).ToList();
            var newProducts = products.Where(p => !existProducts.Select(_ => _.BatchNo).Contains(p.BatchNo, StringComparer.CurrentCultureIgnoreCase)).ToList();
            var removeProducts = existProducts.Where(p => !products.Select(_ => _.BatchNo).Contains(p.BatchNo, StringComparer.CurrentCultureIgnoreCase)).ToList();
            var updateProducts = existProducts.Where(p => products.Select(_ => _.BatchNo).Contains(p.BatchNo, StringComparer.CurrentCultureIgnoreCase)).ToList();

            removeProducts.ForEach(_ =>
            {
                mesDb.CarryOverProducts.Attach(_);
                _.Valid = false;
                _.ModifyBy = model.ModifyBy;
                _.ModifyTime = DateTime.Now;
            });
            updateProducts.ForEach(_ =>
            {
                var product = products.FirstOrDefault(p => StringUtils.Equals(_.BatchNo, p.BatchNo));
                mesDb.CarryOverProducts.Attach(_);
                _.Quantity = product.Quantity;
                _.ModifyBy = model.ModifyBy;
                _.ModifyTime = DateTime.Now;
            });
            mesDb.CarryOverProducts.AddRange(newProducts.Select(_ => new CarryOverProduct
            {
                CarryOverNo = model.CarryOverNo,
                ProductCode = _.ProductCode,
                ProductName = _.ProductName,
                BatchNo = _.BatchNo,
                Quantity = _.Quantity,
                CreateBy = model.ModifyBy,
                CreateTime = DateTime.Now,
            }));

            mesDb.SaveChanges();
        }
    }
}
